package gates;
			
import java.awt.Graphics;
			
import master.*;
			
			
			
/**
* A functional representation of the phase shift gate. Works applying the phase shift to any bit
* and using a register of any size.
* 
* Specify target bit and phase you want to shift it by(as radians), and if that bit is a 1, the 
* gate will shift it's phase by the entered angle
*
* @author Matthew
*
*/
			
			
			
public class PhaseShift extends QuantumGate{
			
int dim;
int bit;
int limit;
int count;
float phase;
			
	private static IllegalArgumentException
	bitException = new IllegalArgumentException("The register is not big enough to work on that bit");
				        
	public PhaseShift(int bit, float phase){
				        
	this.bit = bit;
	this.phase = phase;
				                
	}
				                
				        
	public void actOnReg(QuantumRegister register){
				                
	/**
	* 
	* The loops make sure only the states which have the target qubit as a 1 are looked at
	* The program also makes sure the coefficient of these states isn't 0 as if it is, technically
	* that superposition doesn't exist
	* 
	* 
	* If however the magnitude isn't 0, the state is all shifted by the specified phase shift,			                 * whilst keeping the magnitude the same.
	* 
	*
	*/
	//Catch errors caught by the target bit not being in the register
	if (bit < 0 ||bit >= register.getQBitLength() ){
		throw bitException; 
	}
	
	dim = (int)Math.pow(2, register.getQBitLength());
	limit = (int) ( dim/(Math.pow(2, bit)));
	count = 0;
	
	
	for (int j = 0; j < limit; j++){
	
		for (int i = 0; i < (int)Math.pow(2,bit); i++){

		
				                                        
			if ( j%2 != 0 && (register.getCoefficient(count).magnitudeFloat() != 0.0f)){
                       
				float phase1 = (float) (phase + register.getCoefficient(count).phaseFloat());
				float mag = register.getCoefficient(count).magnitudeFloat();
				
				ComplexNumber temp = ComplexNumber.expi( mag ,phase1 );
				register.setCoefficient(temp, count);
			}
			count ++;
				        
				                                        
		}
	}               
				
	}
				
				        
	public boolean checkDim(QuantumRegister register){
	//checks dimension of matrix compared to dimension of register
		if (register.getDimension() == dim){
			return true;
		}else{
			return false;
		}
	}
			        
				        
	public void draw(Graphics g, int x, int y, float scale) {
		g.fillOval(x+(int)(scale*0.25), y+(int)(scale*0.25)+(int)(scale*bit), (int)(scale*0.5), (int)(scale*0.5));
	}
				        
	
				
				
	public int[] getActingBits() {
		int[] bits = {bit};
		               
		return bits;
	}

}
			
			
